#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
对话框模块
包含各种对话框的实现
"""

import os
import hashlib
import logging
from datetime import datetime
from typing import Optional, List, Dict

from PyQt6.QtWidgets import (
    QDialog, QVBoxLayout, QHBoxLayout, QFormLayout, QLabel,
    QLineEdit, QPushButton, QMessageBox, QComboBox, QSpinBox,
    QTextEdit, QFileDialog, QGroupBox, QCheckBox, QDateEdit,
    QTimeEdit, QScrollArea, QWidget, QGridLayout, QTableWidget,
    QTableWidgetItem, QHeaderView, QAbstractItemView, QDoubleSpinBox
)
from PyQt6.QtCore import Qt, QDate, QTime
from PyQt6.QtGui import QPixmap, QFont, QColor, QPainter

# 使用绝对导入，避免相对导入问题
try:
    from src.core.database_manager import DatabaseManager
    from src.models.models import User, Sample, SampleStatus, UserRole, OperationLog, HospitalInfo, WarningRange
except ImportError:
    # 如果绝对导入失败，尝试相对导入
    try:
        from ..core.database_manager import DatabaseManager
        from ..models.models import User, Sample, SampleStatus, UserRole, OperationLog, HospitalInfo, WarningRange
    except ImportError:
        # 如果都失败，使用字符串导入（延迟导入）
        DatabaseManager = None
        User = Sample = SampleStatus = UserRole = OperationLog = HospitalInfo = WarningRange = None

# 获取logger
logger = logging.getLogger(__name__)

class LoginDialog(QDialog):
    """登录对话框"""
    
    def __init__(self, db_manager: DatabaseManager):
        super().__init__()
        self.db_manager = db_manager
        self.current_user = None
        self.init_ui()
    
    def init_ui(self):
        """初始化UI"""
        self.setWindowTitle("样本管理系统 - 登录")
        self.setFixedSize(400, 300)
        self.setModal(True)
        
        layout = QVBoxLayout()
        
        # 标题
        title_label = QLabel("样本管理系统")
        title_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        title_label.setFont(QFont("Arial", 16, QFont.Weight.Bold))
        layout.addWidget(title_label)
        
        # 登录表单
        form_layout = QFormLayout()
        
        self.username_edit = QLineEdit()
        self.username_edit.setPlaceholderText("请输入用户名")
        form_layout.addRow("用户名:", self.username_edit)
        
        self.password_edit = QLineEdit()
        self.password_edit.setPlaceholderText("请输入密码")
        self.password_edit.setEchoMode(QLineEdit.EchoMode.Password)
        form_layout.addRow("密码:", self.password_edit)
        
        layout.addLayout(form_layout)
        
        # 按钮
        button_layout = QHBoxLayout()
        
        self.login_button = QPushButton("登录")
        self.login_button.clicked.connect(self.login)
        button_layout.addWidget(self.login_button)
        
        self.cancel_button = QPushButton("取消")
        self.cancel_button.clicked.connect(self.reject)
        button_layout.addWidget(self.cancel_button)
        
        layout.addLayout(button_layout)
        
        self.setLayout(layout)
    
    def login(self):
        """登录验证"""
        username = self.username_edit.text().strip()
        password = self.password_edit.text().strip()
        
        if not username or not password:
            QMessageBox.warning(self, "警告", "请输入用户名和密码")
            return
        
        user = self.db_manager.verify_user(username, password)
        if user:
            self.current_user = user
            # 记录登录日志
            log = OperationLog(
                id=0,
                operation_time=datetime.now(),
                operator=user.username,
                operation_type="用户登录",
                operation_content=f"用户 {username} 登录系统",
                ip_address="127.0.0.1"  # 实际应用中应获取真实IP
            )
            self.db_manager.add_operation_log(log)
            
            self.accept()
        else:
            QMessageBox.critical(self, "错误", "用户名或密码错误")

class AdminSetupDialog(QDialog):
    """管理员设置对话框"""
    
    def __init__(self, db_manager: DatabaseManager):
        super().__init__()
        self.db_manager = db_manager
        self.init_ui()
    
    def init_ui(self):
        """初始化UI"""
        self.setWindowTitle("系统初始化 - 创建管理员账号")
        self.setFixedSize(400, 250)
        self.setModal(True)
        
        layout = QVBoxLayout()
        
        # 说明
        info_label = QLabel("首次启动系统，请创建管理员账号")
        info_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        layout.addWidget(info_label)
        
        # 表单
        form_layout = QFormLayout()
        
        self.username_edit = QLineEdit()
        self.username_edit.setPlaceholderText("请输入管理员用户名")
        form_layout.addRow("用户名:", self.username_edit)
        
        self.password_edit = QLineEdit()
        self.password_edit.setPlaceholderText("请输入密码")
        self.password_edit.setEchoMode(QLineEdit.EchoMode.Password)
        form_layout.addRow("密码:", self.password_edit)
        
        self.confirm_password_edit = QLineEdit()
        self.confirm_password_edit.setPlaceholderText("请确认密码")
        self.confirm_password_edit.setEchoMode(QLineEdit.EchoMode.Password)
        form_layout.addRow("确认密码:", self.confirm_password_edit)
        
        layout.addLayout(form_layout)
        
        # 按钮
        button_layout = QHBoxLayout()
        
        self.create_button = QPushButton("创建")
        self.create_button.clicked.connect(self.create_admin)
        button_layout.addWidget(self.create_button)
        
        self.cancel_button = QPushButton("取消")
        self.cancel_button.clicked.connect(self.reject)
        button_layout.addWidget(self.cancel_button)
        
        layout.addLayout(button_layout)
        
        self.setLayout(layout)
    
    def create_admin(self):
        """创建管理员账号"""
        username = self.username_edit.text().strip()
        password = self.password_edit.text().strip()
        confirm_password = self.confirm_password_edit.text().strip()
        
        if not username or not password:
            QMessageBox.warning(self, "警告", "请输入用户名和密码")
            return
        
        if password != confirm_password:
            QMessageBox.warning(self, "警告", "两次输入的密码不一致")
            return
        
        if len(password) < 6:
            QMessageBox.warning(self, "警告", "密码长度至少6位")
            return
        
        if self.db_manager.create_admin_user(username, password):
            QMessageBox.information(self, "成功", "管理员账号创建成功")
            self.accept()
        else:
            QMessageBox.critical(self, "错误", "用户名已存在")

class SampleEditDialog(QDialog):
    """样本编辑对话框"""
    
    def __init__(self, parent=None, sample: Sample = None):
        super().__init__(parent)
        self.sample = sample
        self.parent = parent
        self.init_ui()
        if sample:
            self.load_sample_data()
    
    def init_ui(self):
        """初始化UI"""
        self.setWindowTitle("样本编辑" if self.sample else "新增样本")
        self.setFixedSize(600, 500)
        self.setModal(True)
        
        layout = QVBoxLayout()
        
        # 创建滚动区域
        scroll_area = QScrollArea()
        scroll_widget = QWidget()
        scroll_layout = QFormLayout(scroll_widget)
        
        # 基本信息组
        basic_group = QGroupBox("基本信息")
        basic_layout = QFormLayout(basic_group)
        
        # 样本编号行 - 添加复制按钮
        sample_number_layout = QHBoxLayout()
        self.sample_number_edit = QLineEdit()
        sample_number_layout.addWidget(self.sample_number_edit)
        
        self.copy_sample_button = QPushButton("复制样本")
        self.copy_sample_button.clicked.connect(self.copy_from_existing_sample)
        sample_number_layout.addWidget(self.copy_sample_button)
        
        basic_layout.addRow("样本编号:", sample_number_layout)
        
        # self.sample_id_edit = QLineEdit()
        # basic_layout.addRow("样本ID:", self.sample_id_edit)
        
        self.instrument_id_edit = QLineEdit()
        basic_layout.addRow("仪器ID:", self.instrument_id_edit)
        
        self.instrument_model_edit = QLineEdit()
        basic_layout.addRow("仪器型号:", self.instrument_model_edit)
        
        self.instrument_number_edit = QLineEdit()
        basic_layout.addRow("仪器编号:", self.instrument_number_edit)
        
        self.instrument_type_edit = QLineEdit()
        basic_layout.addRow("仪器类型:", self.instrument_type_edit)
        
        scroll_layout.addRow(basic_group)
        
        # 患者信息组
        patient_group = QGroupBox("患者信息")
        patient_layout = QFormLayout(patient_group)
        
        self.patient_name_edit = QLineEdit()
        patient_layout.addRow("患者姓名:", self.patient_name_edit)
        
        self.patient_age_spin = QSpinBox()
        self.patient_age_spin.setRange(0, 150)
        patient_layout.addRow("年龄:", self.patient_age_spin)
        
        self.patient_gender_combo = QComboBox()
        self.patient_gender_combo.addItems(["", "男", "女"])
        patient_layout.addRow("性别:", self.patient_gender_combo)
        
        scroll_layout.addRow(patient_group)
        
        # 检测信息组
        test_group = QGroupBox("检测信息")
        test_layout = QFormLayout(test_group)
        
        # self.analysis_time_edit = QLineEdit()
        # self.analysis_time_edit.setReadOnly(True)
        # test_layout.addRow("设备分析时间:", self.analysis_time_edit)
        
        # self.protocol_type_edit = QLineEdit()
        # test_layout.addRow("协议类型:", self.protocol_type_edit)
        
        # self.communication_config_edit = QLineEdit()
        # test_layout.addRow("通信配置:", self.communication_config_edit)
        
        self.test_results_edit = QTextEdit()
        self.test_results_edit.setMaximumHeight(100)
        test_layout.addRow("检测结果:", self.test_results_edit)
        
        self.report_id_edit = QLineEdit()
        test_layout.addRow("报告ID:", self.report_id_edit)
        
        self.status_combo = QComboBox()
        self.status_combo.addItems([e.value for e in SampleStatus])
        test_layout.addRow("状态:", self.status_combo)
        
        scroll_layout.addRow(test_group)
        
        scroll_area.setWidget(scroll_widget)
        layout.addWidget(scroll_area)
        
        # 按钮
        button_layout = QHBoxLayout()
        
        self.save_button = QPushButton("保存")
        self.save_button.clicked.connect(self.save_sample_with_log)
        button_layout.addWidget(self.save_button)
        
        self.cancel_button = QPushButton("取消")
        self.cancel_button.clicked.connect(self.reject)
        button_layout.addWidget(self.cancel_button)
        
        layout.addLayout(button_layout)
        
        self.setLayout(layout)
    
    def load_sample_data(self):
        """加载样本数据"""
        if not self.sample:
            return
        
        # 使用新的数据结构
        self.sample_number_edit.setText(self.sample.sample_info.sample_number)
        # self.sample_id_edit.setText(self.sample.sample_info.sample_id)
        self.instrument_id_edit.setText(self.sample.machine_id)
        self.instrument_model_edit.setText(self.sample.machine_model)
        self.instrument_number_edit.setText(self.sample.machine_id)  # 使用machine_id作为仪器编号
        self.instrument_type_edit.setText(self.sample.machine_model)  # 使用machine_model作为仪器类型
        self.patient_name_edit.setText(self.sample.sample_info.patient_name)
        self.patient_age_spin.setValue(self.sample.sample_info.patient_age)
        self.patient_gender_combo.setCurrentText(self.sample.sample_info.patient_gender)
        # self.analysis_time_edit.setText(self.sample.receive_time.strftime("%Y-%m-%d %H:%M:%S"))
        # self.protocol_type_edit.setText(self.sample.protocol)
        # self.communication_config_edit.setText("")  # 新结构中没有这个字段
        self.test_results_edit.setPlainText(self.format_results_for_display(self.sample.results))
        self.report_id_edit.setText(self.sample.sample_info.report_id)
        self.status_combo.setCurrentText(self.sample.status.value)
    
    def format_results_for_display(self, results) -> str:
        """格式化检测结果用于显示"""
        try:
            formatted_results = []
            
            # 基础检测项目
            basic_items = [
                ('HbA1a', results.HbA1a),
                ('HbA1b', results.HbA1b),
                ('HbF', results.HbF),
                ('LA1c', results.LA1c),
                ('HbA1c', results.HbA1c),
                ('HbA0', results.HbA0),
                ('eAG', results.eAG)
            ]
            
            for name, value in basic_items:
                if value:
                    formatted_results.append(f"{name}: {value}")
            
            # 变异筛查项目
            variant_items = [
                ('A2', results.A2),
                ('HbE', results.HbE),
                ('HbD', results.HbD),
                ('HbS', results.HbS),
                ('HbC', results.HbC),
                ('p3', results.p3),
                ('v-win', results.v_win)
            ]
            
            for name, value in variant_items:
                if value:
                    formatted_results.append(f"{name}: {value}")
            
            # TIME数据
            if results.TIME and len(results.TIME) > 0:
                time_values = [str(t) for t in results.TIME if t]
                if time_values:
                    formatted_results.append(f"TIME: {', '.join(time_values)}")
            
            # AREA数据
            if results.AREA and len(results.AREA) > 0:
                area_values = [str(a) for a in results.AREA if a]
                if area_values:
                    formatted_results.append(f"AREA: {', '.join(area_values)}")
            
            return " | ".join(formatted_results)
            
        except Exception as e:
            return "结果格式化失败"

    def get_sample(self) -> Sample:
        """获取样本数据"""
        from src.models.models import SampleInfo, Results, ImageInfo, ModeInfo
        
        # 如果是编辑模式，保持原始ID；如果是新增模式，生成新ID
        if self.sample:
            # 编辑模式：保持原始ID和检测结果数据
            sample_id = self.sample.id
            # 保持原有的检测结果数据
            results = self.sample.results
            image = self.sample.image
            mode_info = self.sample.mode_info
            analysis_mode = self.sample.analysis_mode
            raw = self.sample.raw
            receive_time = self.sample.receive_time
            created_time = self.sample.created_time
        else:
            # 新增模式：生成新ID和空的数据对象
            sample_id = f"SAMPLE_{datetime.now().strftime('%Y%m%d%H%M%S')}"
            results = Results()
            image = ImageInfo()
            mode_info = ModeInfo()
            analysis_mode = ""
            raw = ""
            receive_time = datetime.now()
            created_time = datetime.now()
        
        # 创建SampleInfo对象
        sample_info = SampleInfo(
            sample_id=sample_id,
            sample_number=self.sample_number_edit.text().strip(),
            patient_name=self.patient_name_edit.text().strip(),
            patient_age=self.patient_age_spin.value(),
            patient_gender=self.patient_gender_combo.currentText(),
            datetime=datetime.now().isoformat(),  # 使用ISO格式保持微秒精度
            sample_type="",
            sample_type_name="",
            sample_category="",
            report_id=self.report_id_edit.text().strip(),
            position=""
        )
        
        return Sample(
            id=sample_id,
            protocol="",  # 暂时设为空字符串，因为protocol_type_edit控件已被注释
            machine_model=self.instrument_model_edit.text().strip(),
            machine_id=self.instrument_id_edit.text().strip(),
            sample_info=sample_info,
            results=results,
            image=image,
            analysis_mode=analysis_mode,
            mode_info=mode_info,
            raw=raw,
            receive_time=receive_time,
            status=SampleStatus(self.status_combo.currentText()),
            created_time=created_time,
            updated_time=datetime.now()
        )

    def copy_from_existing_sample(self):
        """从现有样本复制数据"""
        try:
            # 创建样本选择对话框
            dialog = SampleSelectionDialog(self.parent)
            if dialog.exec() == QDialog.DialogCode.Accepted and dialog.selected_sample:
                sample = dialog.selected_sample
                
                # 复制样本数据（除了样本编号和ID）
                self.instrument_id_edit.setText(sample.machine_id or "")
                self.instrument_model_edit.setText(sample.machine_model or "")
                self.instrument_number_edit.setText(sample.machine_id or "")
                self.instrument_type_edit.setText(sample.machine_model or "")
                self.patient_name_edit.setText(sample.sample_info.patient_name or "")
                self.patient_age_spin.setValue(sample.sample_info.patient_age or 0)
                self.patient_gender_combo.setCurrentText(sample.sample_info.patient_gender or "")
                # self.protocol_type_edit.setText(sample.protocol or "")
                # self.communication_config_edit.setText("")  # 新结构中没有这个字段
                self.test_results_edit.setPlainText(self.format_results_for_display(sample.results) if sample.results else "")
                self.report_id_edit.setText(sample.sample_info.report_id or "")
                self.status_combo.setCurrentText(sample.status.value if sample.status else "待检测")
                
                QMessageBox.information(self, "成功", "已从选中样本复制数据")
        except Exception as e:
            QMessageBox.critical(self, "错误", f"复制样本数据失败: {e}")

    def save_sample_with_log(self):
        """保存样本并记录日志"""
        try:
            # 获取编辑后的样本数据
            edited_sample = self.get_sample()
            
            # 记录编辑日志
            self.log_sample_edit(edited_sample)
            
            # 关闭对话框
            self.accept()
            
        except Exception as e:
            logger.error(f"保存样本失败: {e}")
            QMessageBox.critical(self, "错误", f"保存样本失败: {e}")
    
    def log_sample_edit(self, edited_sample: Sample):
        """记录样本编辑日志"""
        try:
            if not self.sample:
                # 新增样本
                self.log_sample_creation(edited_sample)
            else:
                # 编辑样本
                self.log_sample_modification(edited_sample)
                
        except Exception as e:
            logger.error(f"记录样本编辑日志失败: {e}")
    
    def log_sample_creation(self, new_sample: Sample):
        """记录样本创建日志"""
        try:
            # 获取当前用户信息
            current_user = self.get_current_user()
            
            # 创建详细的操作日志内容
            detailed_content = self.format_sample_info_for_log(new_sample)
            log_content = f"新增样本: {new_sample.sample_info.sample_number}, 患者: {new_sample.sample_info.patient_name}\n{detailed_content}"
            
            # 记录到数据库
            self.add_operation_log(
                operation_type="新增样本",
                operation_content=log_content,
                operator=current_user,
                details={
                    "sample_id": new_sample.id,
                    "sample_number": new_sample.sample_info.sample_number,
                    "patient_name": new_sample.sample_info.patient_name,
                    "patient_age": new_sample.sample_info.patient_age,
                    "patient_gender": new_sample.sample_info.patient_gender,
                    "machine_id": new_sample.machine_id,
                    "machine_model": new_sample.machine_model,
                    "status": new_sample.status.value,
                    "detailed_info": detailed_content
                }
            )
            
            logger.info(f"样本创建日志已记录: {log_content}")
            
        except Exception as e:
            logger.error(f"记录样本创建日志失败: {e}")
    
    def log_sample_modification(self, edited_sample: Sample):
        """记录样本修改日志"""
        try:
            # 获取当前用户信息
            current_user = self.get_current_user()
            
            # 比较修改前后的数据
            changes = self.detect_sample_changes(edited_sample)
            
            if not changes:
                logger.info("样本数据未发生变化，跳过日志记录")
                return
            
            # 创建详细的操作日志内容
            detailed_content = self.format_changes_for_log(changes)
            log_content = f"编辑样本: {edited_sample.sample_info.sample_number}, 患者: {edited_sample.sample_info.patient_name}\n{detailed_content}"
            
            # 记录到数据库
            self.add_operation_log(
                operation_type="编辑样本",
                operation_content=log_content,
                operator=current_user,
                details={
                    "sample_id": edited_sample.id,
                    "sample_number": edited_sample.sample_info.sample_number,
                    "patient_name": edited_sample.sample_info.patient_name,
                    "changes": changes,
                    "detailed_changes": detailed_content
                }
            )
            
            logger.info(f"样本修改日志已记录: {log_content}")
            
        except Exception as e:
            logger.error(f"记录样本修改日志失败: {e}")
    
    def detect_sample_changes(self, edited_sample: Sample) -> dict:
        """检测样本数据变化"""
        try:
            if not self.sample:
                return {}
            
            changes = {}
            
            # 检查基本信息变化
            if self.sample.sample_info.sample_number != edited_sample.sample_info.sample_number:
                changes["sample_number"] = {
                    "old": self.sample.sample_info.sample_number,
                    "new": edited_sample.sample_info.sample_number
                }
            
            if self.sample.machine_id != edited_sample.machine_id:
                changes["machine_id"] = {
                    "old": self.sample.machine_id,
                    "new": edited_sample.machine_id
                }
            
            if self.sample.machine_model != edited_sample.machine_model:
                changes["machine_model"] = {
                    "old": self.sample.machine_model,
                    "new": edited_sample.machine_model
                }
            
            # 检查患者信息变化
            if self.sample.sample_info.patient_name != edited_sample.sample_info.patient_name:
                changes["patient_name"] = {
                    "old": self.sample.sample_info.patient_name,
                    "new": edited_sample.sample_info.patient_name
                }
            
            if self.sample.sample_info.patient_age != edited_sample.sample_info.patient_age:
                changes["patient_age"] = {
                    "old": self.sample.sample_info.patient_age,
                    "new": edited_sample.sample_info.patient_age
                }
            
            if self.sample.sample_info.patient_gender != edited_sample.sample_info.patient_gender:
                changes["patient_gender"] = {
                    "old": self.sample.sample_info.patient_gender,
                    "new": edited_sample.sample_info.patient_gender
                }
            
            # 检查状态变化
            if self.sample.status != edited_sample.status:
                changes["status"] = {
                    "old": self.sample.status.value,
                    "new": edited_sample.status.value
                }
            
            # 检查报告ID变化
            if self.sample.sample_info.report_id != edited_sample.sample_info.report_id:
                changes["report_id"] = {
                    "old": self.sample.sample_info.report_id,
                    "new": edited_sample.sample_info.report_id
                }
            
            # 检查检测结果变化（如果有的话）
            if hasattr(self.sample, 'results') and hasattr(edited_sample, 'results'):
                result_changes = self.detect_result_changes(self.sample.results, edited_sample.results)
                if result_changes:
                    changes["test_results"] = result_changes
            
            return changes
            
        except Exception as e:
            logger.error(f"检测样本变化失败: {e}")
            return {}
    
    def detect_result_changes(self, old_results, new_results) -> dict:
        """检测检测结果的变化"""
        try:
            if not old_results or not new_results:
                return {}
            
            changes = {}
            
            # 基础检测项目
            basic_items = [
                ('HbA1a', 'HbA1a'),
                ('HbA1b', 'HbA1b'),
                ('HbF', 'HbF'),
                ('LA1c', 'LA1c'),
                ('HbA1c', 'HbA1c'),
                ('HbA0', 'HbA0'),
                ('eAG', 'eAG')
            ]
            
            for attr_name, display_name in basic_items:
                old_value = getattr(old_results, attr_name, None)
                new_value = getattr(new_results, attr_name, None)
                if old_value != new_value:
                    changes[display_name] = {
                        "old": old_value,
                        "new": new_value
                    }
            
            # 变异筛查项目
            variant_items = [
                ('A2', 'A2'),
                ('HbE', 'HbE'),
                ('HbD', 'HbD'),
                ('HbS', 'HbS'),
                ('HbC', 'HbC'),
                ('p3', 'p3'),
                ('v_win', 'v-win')
            ]
            
            for attr_name, display_name in variant_items:
                old_value = getattr(old_results, attr_name, None)
                new_value = getattr(new_results, attr_name, None)
                if old_value != new_value:
                    changes[display_name] = {
                        "old": old_value,
                        "new": new_value
                    }
            
            return changes
            
        except Exception as e:
            logger.error(f"检测检测结果变化失败: {e}")
            return {}
    
    def get_field_display_name(self, field_name: str) -> str:
        """获取字段的中文显示名称"""
        field_names = {
            "sample_number": "样本编号",
            "machine_id": "仪器ID",
            "machine_model": "仪器型号",
            "patient_name": "患者姓名",
            "patient_age": "患者年龄",
            "patient_gender": "患者性别",
            "status": "样本状态",
            "report_id": "报告ID",
            "test_results": "检测结果"
        }
        return field_names.get(field_name, field_name)
    
    def format_changes_for_log(self, changes: dict) -> str:
        """格式化变更内容用于日志显示"""
        try:
            if not changes:
                return "无变更内容"
            
            formatted_lines = []
            formatted_lines.append("变更详情:")
            
            for field_name, change_info in changes.items():
                display_name = self.get_field_display_name(field_name)
                
                if field_name == "test_results":
                    # 检测结果变化需要特殊处理
                    formatted_lines.append(f"  {display_name}:")
                    for test_name, test_change in change_info.items():
                        old_val = test_change.get("old", "无")
                        new_val = test_change.get("new", "无")
                        formatted_lines.append(f"    {test_name}: {old_val} → {new_val}")
                else:
                    # 普通字段变化
                    old_val = change_info.get("old", "无")
                    new_val = change_info.get("new", "无")
                    formatted_lines.append(f"  {display_name}: {old_val} → {new_val}")
            
            return "\n".join(formatted_lines)
            
        except Exception as e:
            logger.error(f"格式化变更内容失败: {e}")
            return f"格式化失败: {e}"
    
    def format_sample_info_for_log(self, sample: Sample) -> str:
        """格式化样本信息用于日志显示"""
        try:
            formatted_lines = []
            formatted_lines.append("样本详情:")
            
            # 基本信息
            formatted_lines.append("  基本信息:")
            formatted_lines.append(f"    样本编号: {sample.sample_info.sample_number}")
            formatted_lines.append(f"    样本ID: {sample.id}")
            formatted_lines.append(f"    仪器ID: {sample.machine_id}")
            formatted_lines.append(f"    仪器型号: {sample.machine_model}")
            
            # 患者信息
            formatted_lines.append("  患者信息:")
            formatted_lines.append(f"    姓名: {sample.sample_info.patient_name}")
            formatted_lines.append(f"    年龄: {sample.sample_info.patient_age}")
            formatted_lines.append(f"    性别: {sample.sample_info.patient_gender}")
            
            # 检测信息
            formatted_lines.append("  检测信息:")
            formatted_lines.append(f"    状态: {sample.status.value}")
            formatted_lines.append(f"    报告ID: {sample.sample_info.report_id}")
            formatted_lines.append(f"    接收时间: {sample.receive_time.isoformat()}")
            
            # 检测结果（如果有的话）
            if hasattr(sample, 'results') and sample.results:
                formatted_lines.append("  检测结果:")
                results_summary = self.format_results_for_display(sample.results)
                if results_summary and results_summary != "结果格式化失败":
                    formatted_lines.append(f"    {results_summary}")
                else:
                    formatted_lines.append("    暂无检测结果")
            
            return "\n".join(formatted_lines)
            
        except Exception as e:
            logger.error(f"格式化样本信息失败: {e}")
            return f"格式化失败: {e}"
    
    def get_current_user(self) -> str:
        """获取当前用户信息"""
        try:
            # 尝试从父窗口获取当前用户
            if self.parent and hasattr(self.parent, 'current_user') and self.parent.current_user:
                return self.parent.current_user.username
            else:
                return "未知用户"
        except Exception as e:
            logger.error(f"获取当前用户失败: {e}")
            return "未知用户"
    
    def add_operation_log(self, operation_type: str, operation_content: str, 
                          operator: str, details: dict = None):
        """添加操作日志到数据库"""
        try:
            # 尝试从父窗口获取数据库管理器
            if self.parent and hasattr(self.parent, 'db_manager') and self.parent.db_manager:
                from src.models.models import OperationLog
                from datetime import datetime
                
                # 创建操作日志对象
                log = OperationLog(
                    id=0,
                    operation_time=datetime.now(),
                    operator=operator,
                    operation_type=operation_type,
                    operation_content=operation_content,
                    ip_address="127.0.0.1"  # 实际应用中应获取真实IP
                )
                
                # 添加到数据库
                self.parent.db_manager.add_operation_log(log)
                logger.info(f"操作日志已添加到数据库: {operation_type}")
                
            else:
                logger.warning("无法获取数据库管理器，跳过日志记录")
                
        except Exception as e:
            logger.error(f"添加操作日志失败: {e}")

class ImageViewerDialog(QDialog):
    """图片查看器对话框"""
    
    def __init__(self, image_path: str, parent=None):
        super().__init__(parent)
        self.image_path = image_path
        self.init_ui()
    
    def init_ui(self):
        """初始化UI"""
        self.setWindowTitle("图片查看器")
        self.setFixedSize(800, 600)
        self.setModal(True)
        
        layout = QVBoxLayout()
        
        # 图片显示
        image_label = QLabel()
        pixmap = QPixmap(self.image_path)
        if not pixmap.isNull():
            # 缩放图片以适应窗口
            scaled_pixmap = pixmap.scaled(
                780, 550, 
                Qt.AspectRatioMode.KeepAspectRatio, 
                Qt.TransformationMode.SmoothTransformation
            )
            image_label.setPixmap(scaled_pixmap)
            image_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        else:
            image_label.setText("无法加载图片")
            image_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        
        layout.addWidget(image_label)
        
        # 按钮
        button_layout = QHBoxLayout()
        
        self.close_button = QPushButton("关闭")
        self.close_button.clicked.connect(self.accept)
        button_layout.addWidget(self.close_button)
        
        layout.addLayout(button_layout)
        
        self.setLayout(layout)



class WarningRangeDialog(QDialog):
    """警告区间配置对话框"""
    
    def __init__(self, parent=None, warning_range=None):
        super().__init__(parent)
        self.warning_range = warning_range
        self.init_ui()
        if warning_range:
            self.load_warning_range(warning_range)
    
    def init_ui(self):
        """初始化UI"""
        self.setWindowTitle("警告区间配置")
        self.setFixedSize(400, 300)
        self.setModal(True)
        
        layout = QVBoxLayout()
        
        # 表单布局
        form_layout = QFormLayout()
        
        # 检测项目名称
        self.test_name_edit = QLineEdit()
        self.test_name_edit.setPlaceholderText("例如: HbA1c, 血糖, 胆固醇")
        form_layout.addRow("检测项目:", self.test_name_edit)
        
        # 最小值
        self.min_value_spin = QDoubleSpinBox()
        self.min_value_spin.setRange(-9999, 9999)
        self.min_value_spin.setDecimals(2)
        form_layout.addRow("最小值:", self.min_value_spin)
        
        # 最大值
        self.max_value_spin = QDoubleSpinBox()
        self.max_value_spin.setRange(-9999, 9999)
        self.max_value_spin.setDecimals(2)
        form_layout.addRow("最大值:", self.max_value_spin)
        
        # 单位
        self.unit_edit = QLineEdit()
        self.unit_edit.setPlaceholderText("例如: %, mmol/L, mg/dL")
        form_layout.addRow("单位:", self.unit_edit)
        
        # 警告颜色
        self.warning_color_combo = QComboBox()
        self.warning_color_combo.addItems(["red", "orange", "yellow", "blue"])
        form_layout.addRow("警告颜色:", self.warning_color_combo)
        
        layout.addLayout(form_layout)
        
        # 说明文本
        info_label = QLabel("说明: 当检测值超出设定范围时，将在报告中以指定颜色高亮显示")
        info_label.setWordWrap(True)
        info_label.setStyleSheet("color: #7f8c8d; font-size: 10px;")
        layout.addWidget(info_label)
        
        # 按钮
        button_layout = QHBoxLayout()
        
        self.ok_button = QPushButton("确定")
        self.ok_button.clicked.connect(self.accept)
        button_layout.addWidget(self.ok_button)
        
        self.cancel_button = QPushButton("取消")
        self.cancel_button.clicked.connect(self.reject)
        button_layout.addWidget(self.cancel_button)
        
        layout.addLayout(button_layout)
        
        self.setLayout(layout)
    
    def load_warning_range(self, warning_range):
        """加载警告区间数据"""
        try:
            self.test_name_edit.setText(warning_range.test_name)
            self.min_value_spin.setValue(warning_range.min_value)
            self.max_value_spin.setValue(warning_range.max_value)
            self.unit_edit.setText(warning_range.unit)
            
            # 设置警告颜色
            index = self.warning_color_combo.findText(warning_range.warning_color)
            if index >= 0:
                self.warning_color_combo.setCurrentIndex(index)
        except Exception as e:
            logger.error(f"加载警告区间数据失败: {e}")
    
    def get_warning_range(self) -> WarningRange:
        """获取警告区间数据"""
        try:
            from datetime import datetime
            
            return WarningRange(
                test_name=self.test_name_edit.text().strip(),
                min_value=self.min_value_spin.value(),
                max_value=self.max_value_spin.value(),
                unit=self.unit_edit.text().strip(),
                warning_color=self.warning_color_combo.currentText(),
                created_time=datetime.now()
            )
        except Exception as e:
            logger.error(f"获取警告区间数据失败: {e}")
            return None

class LogDetailsDialog(QDialog):
    """日志详情对话框"""
    
    def __init__(self, log: OperationLog, parent=None):
        super().__init__(parent)
        self.log = log
        self.init_ui()
        self.load_log_data()
    
    def init_ui(self):
        """初始化UI"""
        self.setWindowTitle("日志详情")
        self.setFixedSize(600, 400)
        self.setModal(True)
        
        layout = QVBoxLayout()
        
        # 日志信息组
        info_group = QGroupBox("日志信息")
        info_group.setFont(QFont("Arial", 10, QFont.Weight.Bold))
        info_layout = QFormLayout(info_group)
        
        # 日志ID
        self.log_id_label = QLabel()
        info_layout.addRow("日志ID:", self.log_id_label)
        
        # 操作时间
        self.operation_time_label = QLabel()
        info_layout.addRow("操作时间:", self.operation_time_label)
        
        # 操作者
        self.operator_label = QLabel()
        info_layout.addRow("操作者:", self.operator_label)
        
        # 操作类型
        self.operation_type_label = QLabel()
        info_layout.addRow("操作类型:", self.operation_type_label)
        
        # IP地址
        self.ip_address_label = QLabel()
        info_layout.addRow("IP地址:", self.ip_address_label)
        
        layout.addWidget(info_group)
        
        # 操作内容组
        content_group = QGroupBox("操作内容")
        content_group.setFont(QFont("Arial", 10, QFont.Weight.Bold))
        content_layout = QVBoxLayout(content_group)
        
        self.operation_content_text = QTextEdit()
        self.operation_content_text.setReadOnly(True)
        self.operation_content_text.setMaximumHeight(150)
        self.operation_content_text.setStyleSheet("""
            QTextEdit {
                border: 1px solid #bdc3c7;
                background-color: #f8f9fa;
                padding: 10px;
                font-family: Consolas, Monaco, monospace;
                font-size: 9px;
            }
        """)
        content_layout.addWidget(self.operation_content_text)
        
        layout.addWidget(content_group)
        
        # 按钮
        button_layout = QHBoxLayout()
        
        self.close_button = QPushButton("关闭")
        self.close_button.clicked.connect(self.accept)
        button_layout.addWidget(self.close_button)
        
        self.copy_button = QPushButton("复制内容")
        self.copy_button.clicked.connect(self.copy_content)
        button_layout.addWidget(self.copy_button)
        
        layout.addLayout(button_layout)
        
        self.setLayout(layout)
    
    def load_log_data(self):
        """加载日志数据"""
        try:
            # 设置日志信息
            self.log_id_label.setText(str(self.log.id))
            self.operation_time_label.setText(self.log.operation_time.strftime("%Y-%m-%d %H:%M:%S"))
            self.operator_label.setText(self.log.operator)
            self.operation_type_label.setText(self.log.operation_type)
            self.ip_address_label.setText(self.log.ip_address or "未知")
            
            # 设置操作内容
            self.operation_content_text.setPlainText(self.log.operation_content)
            
        except Exception as e:
            logger.error(f"加载日志数据失败: {e}")
            QMessageBox.critical(self, "错误", f"加载日志数据失败: {e}")
    
    def copy_content(self):
        """复制操作内容到剪贴板"""
        try:
            from PyQt6.QtWidgets import QApplication
            
            content = self.log.operation_content
            QApplication.clipboard().setText(content)
            
            QMessageBox.information(self, "成功", "操作内容已复制到剪贴板")
            
        except Exception as e:
            logger.error(f"复制内容失败: {e}")
            QMessageBox.critical(self, "错误", f"复制内容失败: {e}")

class SampleSelectionDialog(QDialog):
    """样本选择对话框"""
    
    def __init__(self, parent=None):
        super().__init__(parent)
        self.selected_sample = None
        self.db_manager = DatabaseManager()
        self.init_ui()
        self.load_samples()
    
    def init_ui(self):
        """初始化UI"""
        self.setWindowTitle("选择样本")
        self.setFixedSize(800, 600)
        self.setModal(True)
        
        layout = QVBoxLayout()
        
        # 搜索区域
        search_layout = QHBoxLayout()
        
        search_layout.addWidget(QLabel("搜索:"))
        self.search_edit = QLineEdit()
        self.search_edit.setPlaceholderText("输入样本编号、患者姓名或样本ID")
        self.search_edit.textChanged.connect(self.on_search_changed)
        search_layout.addWidget(self.search_edit)
        
        self.search_button = QPushButton("搜索")
        self.search_button.clicked.connect(self.search_samples)
        search_layout.addWidget(self.search_button)
        
        layout.addLayout(search_layout)
        
        # 样本表格
        self.samples_table = QTableWidget()
        self.samples_table.setColumnCount(6)
        self.samples_table.setHorizontalHeaderLabels([
            "样本编号", "患者姓名", "患者年龄", "患者性别", "设备分析时间", "状态"
        ])
        
        # 设置表格属性
        header = self.samples_table.horizontalHeader()
        header.setSectionResizeMode(0, QHeaderView.ResizeMode.ResizeToContents)
        header.setSectionResizeMode(1, QHeaderView.ResizeMode.Stretch)
        header.setSectionResizeMode(2, QHeaderView.ResizeMode.ResizeToContents)
        header.setSectionResizeMode(3, QHeaderView.ResizeMode.ResizeToContents)
        header.setSectionResizeMode(4, QHeaderView.ResizeMode.ResizeToContents)
        header.setSectionResizeMode(5, QHeaderView.ResizeMode.ResizeToContents)
        
        self.samples_table.setSelectionBehavior(QTableWidget.SelectionBehavior.SelectRows)
        self.samples_table.setAlternatingRowColors(True)
        self.samples_table.doubleClicked.connect(self.on_sample_double_clicked)
        
        layout.addWidget(self.samples_table)
        
        # 按钮
        button_layout = QHBoxLayout()
        
        self.select_button = QPushButton("选择")
        self.select_button.clicked.connect(self.select_sample)
        button_layout.addWidget(self.select_button)
        
        self.cancel_button = QPushButton("取消")
        self.cancel_button.clicked.connect(self.reject)
        button_layout.addWidget(self.cancel_button)
        
        layout.addLayout(button_layout)
        
        self.setLayout(layout)
    
    def load_samples(self):
        """加载样本列表"""
        try:
            samples = self.db_manager.get_samples()
            
            self.samples_table.setRowCount(len(samples))
            for row, sample in enumerate(samples):
                self.samples_table.setItem(row, 0, QTableWidgetItem(sample.sample_info.sample_number))
                self.samples_table.setItem(row, 1, QTableWidgetItem(sample.sample_info.patient_name))
                self.samples_table.setItem(row, 2, QTableWidgetItem(str(sample.sample_info.patient_age)))
                self.samples_table.setItem(row, 3, QTableWidgetItem(sample.sample_info.patient_gender))
                self.samples_table.setItem(row, 4, QTableWidgetItem(sample.receive_time.strftime("%Y-%m-%d %H:%M:%S")))
                self.samples_table.setItem(row, 5, QTableWidgetItem(sample.status.value))
                
                # 存储样本对象
                self.samples_table.item(row, 0).setData(Qt.ItemDataRole.UserRole, sample)
            
        except Exception as e:
            logger.error(f"加载样本列表失败: {e}")
            QMessageBox.critical(self, "错误", f"加载样本列表失败: {e}")
    
    def search_samples(self):
        """搜索样本"""
        try:
            search_text = self.search_edit.text().strip()
            if not search_text:
                self.load_samples()
                return
            
            filters = {
                "sample_number": search_text,
                "patient_name": search_text,
                "sample_id": search_text
            }
            samples = self.db_manager.get_samples(filters)
            
            self.samples_table.setRowCount(len(samples))
            for row, sample in enumerate(samples):
                self.samples_table.setItem(row, 0, QTableWidgetItem(sample.sample_info.sample_number))
                self.samples_table.setItem(row, 1, QTableWidgetItem(sample.sample_info.patient_name))
                self.samples_table.setItem(row, 2, QTableWidgetItem(str(sample.sample_info.patient_age)))
                self.samples_table.setItem(row, 3, QTableWidgetItem(sample.sample_info.patient_gender))
                self.samples_table.setItem(row, 4, QTableWidgetItem(sample.receive_time.strftime("%Y-%m-%d %H:%M:%S")))
                self.samples_table.setItem(row, 5, QTableWidgetItem(sample.status.value))
                
                # 存储样本对象
                self.samples_table.item(row, 0).setData(Qt.ItemDataRole.UserRole, sample)
            
        except Exception as e:
            logger.error(f"搜索样本失败: {e}")
            QMessageBox.critical(self, "错误", f"搜索样本失败: {e}")
    
    def on_search_changed(self):
        """搜索文本改变时自动搜索"""
        # 可以添加防抖逻辑
        pass
    
    def on_sample_double_clicked(self, index):
        """双击样本时选择"""
        self.select_sample()
    
    def select_sample(self):
        """选择样本"""
        try:
            current_row = self.samples_table.currentRow()
            if current_row < 0:
                QMessageBox.warning(self, "警告", "请先选择一个样本")
                return
            
            # 获取选中的样本
            item = self.samples_table.item(current_row, 0)
            if item:
                self.selected_sample = item.data(Qt.ItemDataRole.UserRole)
                self.accept()
            else:
                QMessageBox.warning(self, "警告", "无法获取选中的样本")
                
        except Exception as e:
            logger.error(f"选择样本失败: {e}")
            QMessageBox.critical(self, "错误", f"选择样本失败: {e}") 

class PatientInfoDialog(QDialog):
    """患者信息编辑对话框"""
    
    def __init__(self, parent=None, patient_name="", patient_age=0, patient_gender=""):
        super().__init__(parent)
        self.patient_name = patient_name
        self.patient_age = patient_age
        self.patient_gender = patient_gender
        self.init_ui()
    
    def init_ui(self):
        """初始化UI"""
        self.setWindowTitle("患者信息编辑")
        self.setFixedSize(400, 300)
        self.setModal(True)
        
        layout = QVBoxLayout()
        
        # 标题
        title_label = QLabel("患者信息")
        title_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        title_label.setFont(QFont("Arial", 14, QFont.Weight.Bold))
        layout.addWidget(title_label)
        
        # 表单
        form_layout = QFormLayout()
        
        # 患者姓名
        self.patient_name_edit = QLineEdit()
        self.patient_name_edit.setPlaceholderText("请输入患者姓名")
        self.patient_name_edit.setText(self.patient_name)
        form_layout.addRow("患者姓名:", self.patient_name_edit)
        
        # 患者年龄
        self.patient_age_spin = QSpinBox()
        self.patient_age_spin.setRange(0, 150)
        self.patient_age_spin.setValue(self.patient_age)
        self.patient_age_spin.setSuffix(" 岁")
        form_layout.addRow("患者年龄:", self.patient_age_spin)
        
        # 患者性别
        self.patient_gender_combo = QComboBox()
        self.patient_gender_combo.addItems(["", "男", "女", "其他"])
        if self.patient_gender:
            index = self.patient_gender_combo.findText(self.patient_gender)
            if index >= 0:
                self.patient_gender_combo.setCurrentIndex(index)
        form_layout.addRow("患者性别:", self.patient_gender_combo)
        
        layout.addLayout(form_layout)
        
        # 按钮
        button_layout = QHBoxLayout()
        
        self.save_button = QPushButton("保存")
        self.save_button.clicked.connect(self.accept)
        button_layout.addWidget(self.save_button)
        
        self.cancel_button = QPushButton("取消")
        self.cancel_button.clicked.connect(self.reject)
        button_layout.addWidget(self.cancel_button)
        
        layout.addLayout(button_layout)
        
        self.setLayout(layout)
    
    def get_patient_info(self):
        """获取患者信息"""
        return {
            "patient_name": self.patient_name_edit.text().strip(),
            "patient_age": self.patient_age_spin.value(),
            "patient_gender": self.patient_gender_combo.currentText()
        } 


class UserEditDialog(QDialog):
    """用户编辑对话框"""
    
    def __init__(self, parent=None, user: User = None):
        super().__init__(parent)
        self.user = user
        self.is_edit_mode = user is not None
        self.init_ui()
    
    def init_ui(self):
        """初始化UI"""
        if self.is_edit_mode:
            self.setWindowTitle("编辑用户")
        else:
            self.setWindowTitle("新增用户")
        
        self.setFixedSize(400, 300)
        self.setModal(True)
        
        layout = QVBoxLayout()
        
        # 标题
        title_label = QLabel("用户信息")
        title_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        title_label.setFont(QFont("Arial", 14, QFont.Weight.Bold))
        layout.addWidget(title_label)
        
        # 表单
        form_layout = QFormLayout()
        
        self.username_edit = QLineEdit()
        self.username_edit.setPlaceholderText("请输入用户名")
        form_layout.addRow("用户名:", self.username_edit)
        
        self.password_edit = QLineEdit()
        self.password_edit.setPlaceholderText("请输入密码")
        self.password_edit.setEchoMode(QLineEdit.EchoMode.Password)
        form_layout.addRow("密码:", self.password_edit)
        
        self.confirm_password_edit = QLineEdit()
        self.confirm_password_edit.setPlaceholderText("请确认密码")
        self.confirm_password_edit.setEchoMode(QLineEdit.EchoMode.Password)
        form_layout.addRow("确认密码:", self.confirm_password_edit)
        
        self.role_combo = QComboBox()
        self.role_combo.addItems([role.value for role in UserRole])
        form_layout.addRow("用户角色:", self.role_combo)
        
        layout.addLayout(form_layout)
        
        # 按钮
        button_layout = QHBoxLayout()
        
        self.save_button = QPushButton("保存")
        self.save_button.clicked.connect(self.save_user)
        button_layout.addWidget(self.save_button)
        
        self.cancel_button = QPushButton("取消")
        self.cancel_button.clicked.connect(self.reject)
        button_layout.addWidget(self.cancel_button)
        
        layout.addLayout(button_layout)
        
        self.setLayout(layout)
        
        # 如果是编辑模式，填充现有数据
        if self.is_edit_mode:
            self.fill_user_data()
    
    def fill_user_data(self):
        """填充用户数据"""
        if self.user:
            self.username_edit.setText(self.user.username)
            self.role_combo.setCurrentText(self.user.role.value)
            # 编辑模式下密码字段留空
            self.password_edit.setPlaceholderText("留空表示不修改密码")
            self.confirm_password_edit.setPlaceholderText("留空表示不修改密码")
    
    def save_user(self):
        """保存用户"""
        username = self.username_edit.text().strip()
        password = self.password_edit.text()
        confirm_password = self.confirm_password_edit.text()
        role_text = self.role_combo.currentText()
        
        # 验证输入
        if not username:
            QMessageBox.warning(self, "警告", "请输入用户名")
            return
        
        if not self.is_edit_mode:
            # 新增模式下密码必填
            if not password:
                QMessageBox.warning(self, "警告", "请输入密码")
                return
        
        if password and password != confirm_password:
            QMessageBox.warning(self, "警告", "两次输入的密码不一致")
            return
        
        # 获取角色枚举
        role = None
        for user_role in UserRole:
            if user_role.value == role_text:
                role = user_role
                break
        
        if not role:
            QMessageBox.critical(self, "错误", "无效的用户角色")
            return
        
        # 保存用户信息
        self.user_data = {
            "username": username,
            "password": password if password else None,
            "role": role
        }
        
        self.accept()
    
    def get_user_data(self) -> dict:
        """获取用户数据"""
        return getattr(self, 'user_data', {})


class UserPasswordDialog(QDialog):
    """用户密码修改对话框"""
    
    def __init__(self, parent=None, username: str = ""):
        super().__init__(parent)
        self.username = username
        self.init_ui()
    
    def init_ui(self):
        """初始化UI"""
        self.setWindowTitle("修改密码")
        self.setFixedSize(350, 200)
        self.setModal(True)
        
        layout = QVBoxLayout()
        
        # 标题
        title_label = QLabel(f"修改用户 '{self.username}' 的密码")
        title_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        title_label.setFont(QFont("Arial", 12, QFont.Weight.Bold))
        layout.addWidget(title_label)
        
        # 表单
        form_layout = QFormLayout()
        
        self.new_password_edit = QLineEdit()
        self.new_password_edit.setPlaceholderText("请输入新密码")
        self.new_password_edit.setEchoMode(QLineEdit.EchoMode.Password)
        form_layout.addRow("新密码:", self.new_password_edit)
        
        self.confirm_password_edit = QLineEdit()
        self.confirm_password_edit.setPlaceholderText("请确认新密码")
        self.confirm_password_edit.setEchoMode(QLineEdit.EchoMode.Password)
        form_layout.addRow("确认密码:", self.confirm_password_edit)
        
        layout.addLayout(form_layout)
        
        # 按钮
        button_layout = QHBoxLayout()
        
        self.save_button = QPushButton("保存")
        self.save_button.clicked.connect(self.save_password)
        button_layout.addWidget(self.save_button)
        
        self.cancel_button = QPushButton("取消")
        self.cancel_button.clicked.connect(self.reject)
        button_layout.addWidget(self.cancel_button)
        
        layout.addLayout(button_layout)
        
        self.setLayout(layout)
    
    def save_password(self):
        """保存密码"""
        new_password = self.new_password_edit.text()
        confirm_password = self.confirm_password_edit.text()
        
        # 验证输入
        if not new_password:
            QMessageBox.warning(self, "警告", "请输入新密码")
            return
        
        if new_password != confirm_password:
            QMessageBox.warning(self, "警告", "两次输入的密码不一致")
            return
        
        self.new_password = new_password
        self.accept()
    
    def get_new_password(self) -> str:
        """获取新密码"""
        return getattr(self, 'new_password', "")


class UserPermissionDialog(QDialog):
    """用户权限管理对话框"""
    
    def __init__(self, parent=None, user: User = None):
        super().__init__(parent)
        self.user = user
        self.init_ui()
    
    def init_ui(self):
        """初始化UI"""
        self.setWindowTitle("用户权限管理")
        self.setFixedSize(500, 400)
        self.setModal(True)
        
        layout = QVBoxLayout()
        
        # 标题
        title_label = QLabel(f"管理用户 '{self.user.username if self.user else ''}' 的权限")
        title_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        title_label.setFont(QFont("Arial", 12, QFont.Weight.Bold))
        layout.addWidget(title_label)
        
        # 权限组
        permission_group = QGroupBox("功能权限")
        permission_layout = QVBoxLayout(permission_group)
        
        # 样本管理权限
        self.sample_manage_checkbox = QCheckBox("样本管理")
        self.sample_manage_checkbox.setToolTip("允许查看、添加、编辑、删除样本")
        permission_layout.addWidget(self.sample_manage_checkbox)
        
        # 日志查看权限
        self.log_view_checkbox = QCheckBox("日志查看")
        self.log_view_checkbox.setToolTip("允许查看系统日志")
        permission_layout.addWidget(self.log_view_checkbox)
        
        # 高级功能权限（仅管理员）
        self.advanced_permissions_group = QGroupBox("高级功能权限（仅管理员）")
        advanced_layout = QVBoxLayout(self.advanced_permissions_group)
        
        self.sample_export_checkbox = QCheckBox("样本导出")
        self.sample_export_checkbox.setToolTip("允许导出样本数据")
        advanced_layout.addWidget(self.sample_export_checkbox)
        
        self.sample_send_checkbox = QCheckBox("样本发送")
        self.sample_send_checkbox.setToolTip("允许发送样本到其他系统")
        advanced_layout.addWidget(self.sample_send_checkbox)
        
        # 用户管理权限
        self.user_manage_checkbox = QCheckBox("用户管理")
        self.user_manage_checkbox.setToolTip("允许管理其他用户")
        advanced_layout.addWidget(self.user_manage_checkbox)
        
        # 系统设置权限
        self.system_settings_checkbox = QCheckBox("系统设置")
        self.system_settings_checkbox.setToolTip("允许修改系统配置")
        advanced_layout.addWidget(self.system_settings_checkbox)
        
        # 备份管理权限
        self.backup_manage_checkbox = QCheckBox("备份管理")
        self.backup_manage_checkbox.setToolTip("允许创建和管理备份")
        advanced_layout.addWidget(self.backup_manage_checkbox)
        
        advanced_layout.addWidget(self.advanced_permissions_group)
        
        layout.addWidget(permission_group)
        
        # 说明
        info_label = QLabel("注意：权限设置基于用户角色，管理员拥有所有权限")
        info_label.setStyleSheet("color: gray; font-size: 10px;")
        layout.addWidget(info_label)
        
        # 按钮
        button_layout = QHBoxLayout()
        
        self.save_button = QPushButton("保存")
        self.save_button.clicked.connect(self.save_permissions)
        button_layout.addWidget(self.save_button)
        
        self.cancel_button = QPushButton("取消")
        self.cancel_button.clicked.connect(self.reject)
        button_layout.addWidget(self.cancel_button)
        
        layout.addLayout(button_layout)
        
        self.setLayout(layout)
        
        # 根据用户角色设置权限
        if self.user:
            self.set_permissions_by_role()
    
    def set_permissions_by_role(self):
        """根据用户角色设置权限"""
        if not self.user:
            return
        
        # 管理员拥有所有权限
        if self.user.role == UserRole.ADMIN:
            self.sample_manage_checkbox.setChecked(True)
            self.sample_export_checkbox.setChecked(True)
            self.sample_send_checkbox.setChecked(True)
            self.user_manage_checkbox.setChecked(True)
            self.system_settings_checkbox.setChecked(True)
            self.log_view_checkbox.setChecked(True)
            self.backup_manage_checkbox.setChecked(True)
            
            # 管理员权限不可修改
            self.sample_manage_checkbox.setEnabled(False)
            self.sample_export_checkbox.setEnabled(False)
            self.sample_send_checkbox.setEnabled(False)
            self.user_manage_checkbox.setEnabled(False)
            self.system_settings_checkbox.setEnabled(False)
            self.log_view_checkbox.setEnabled(False)
            self.backup_manage_checkbox.setEnabled(False)
            
            # 高级权限组可用
            self.advanced_permissions_group.setEnabled(True)
        
        # 查看员只有基础权限
        elif self.user.role == UserRole.VIEWER:
            self.sample_manage_checkbox.setChecked(True)
            self.sample_export_checkbox.setChecked(False)
            self.sample_send_checkbox.setChecked(False)
            self.user_manage_checkbox.setChecked(False)
            self.system_settings_checkbox.setChecked(False)
            self.log_view_checkbox.setChecked(True)
            self.backup_manage_checkbox.setChecked(False)
            
            # 查看员权限不可修改
            self.sample_manage_checkbox.setEnabled(False)
            self.log_view_checkbox.setEnabled(False)
            
            # 高级权限组不可用
            self.advanced_permissions_group.setEnabled(False)
    
    def save_permissions(self):
        """保存权限设置"""
        # 这里可以保存权限设置到数据库
        # 目前只是演示，实际应用中需要创建权限表
        permissions = {
            "sample_manage": self.sample_manage_checkbox.isChecked(),
            "sample_export": self.sample_export_checkbox.isChecked(),
            "sample_send": self.sample_send_checkbox.isChecked(),
            "user_manage": self.user_manage_checkbox.isChecked(),
            "system_settings": self.system_settings_checkbox.isChecked(),
            "log_view": self.log_view_checkbox.isChecked(),
            "backup_manage": self.backup_manage_checkbox.isChecked()
        }
        
        self.permissions_data = permissions
        self.accept()
    
    def get_permissions(self) -> dict:
        """获取权限设置"""
        return getattr(self, 'permissions_data', {}) 